/* eslint-disable jsdoc/require-returns */
import eslint from "eslint";

/**
 * ESLint Rule 测试脚本
 * 用于测试自定义 ESLint 规则
 */
class ESLintRuleTester {
  constructor(options = {}) {
    this.options = {
      fix: options.fix || false,
      ...options,
    };

    this.engine = new eslint.ESLint(this.options);
  }

  /**
   * 测试单个规则
   * @param {string} ruleName 规则名称
   * @param {string} code 要测试的代码
   * @param {string|Array<string|number>} ruleConfig 规则配置
   * @returns {Promise<unknown>} 测试结果
   */
  async testRule(ruleName, code, ruleConfig = "error") {
    const linter = new eslint.Linter();
    const messages = linter.verify(code, {
      rules: {
        [ruleName]: ruleConfig,
      },
    });

    return {
      ruleName,
      code,
      messages,
      hasErrors: messages.some((msg) => msg.severity === 2),
      hasWarnings: messages.some((msg) => msg.severity === 1),
      errorCount: messages.filter((msg) => msg.severity === 2).length,
      warningCount: messages.filter((msg) => msg.severity === 1).length,
    };
  }

  /**
   * 批量测试多个规则
   * @param {Array<{ruleName: string, code: string, ruleConfig?: string|Array<string|number>, description?: string, shouldPass?: boolean}>} testCases 测试用例数组
   * @returns {Promise<Array<unknown>>} 所有测试结果
   */
  async testRules(testCases) {
    const results = [];

    for (const testCase of testCases) {
      const result = await this.testRule(
        testCase.ruleName,
        testCase.code,
        testCase.ruleConfig,
      );
      results.push({
        ...result,
        description: testCase.description,
        shouldPass: testCase.shouldPass || false,
      });
    }

    return results;
  }

  /**
   * 生成测试报告
   * @param {Array<{ruleName: string, code: string, ruleConfig?: string|Array<string|number>, description?: string, shouldPass?: boolean}>  } results 测试结果
   */
  generateReport(results) {
    console.log("\n📋 ESLint Rule 测试报告\n");

    const totalTests = results.length;
    let passedTests = 0;
    let failedTests = 0;

    for (const [index, result] of results.entries()) {
      console.log(
        `📝 测试用例 ${index + 1}: ${result.description || result.ruleName}`,
      );
      console.log(`   规则: ${result.ruleName}`);
      console.log(
        `   代码: ${result.code.replaceAll("\n", " ").slice(0, 50)}...`,
      );

      if (result.messages.length === 0) {
        console.log("   ✅ 通过: 无错误或警告");
        passedTests++;
      } else {
        console.log(`   ❌ 失败: ${result.messages.length} 个问题`);
        for (const msg of result.messages) {
          const severity = msg.severity === 2 ? "错误" : "警告";
          console.log(
            `      ${severity}: ${msg.message} (行 ${msg.line}, 列 ${msg.column})`,
          );
        }
        failedTests++;
      }
      console.log("");
    }

    console.log("📊 测试总结:");
    console.log(`   总测试用例: ${totalTests}`);
    console.log(`   通过: ${passedTests}`);
    console.log(`   失败: ${failedTests}`);
    console.log(
      `   成功率: ${((passedTests / totalTests) * 100).toFixed(1)}%\n`,
    );

    return {
      totalTests,
      passedTests,
      failedTests,
      successRate: (passedTests / totalTests) * 100,
    };
  }
}

/**
 * 示例测试用例
 */
const exampleTestCases = [
  {
    ruleName: "no-console",
    code: "console.log('hello world');",
    ruleConfig: "error",
    description: "测试 console.log 应该报错",
    shouldPass: false,
  },
  {
    ruleName: "no-console",
    code: "// console.log('commented out');",
    ruleConfig: "error",
    description: "测试注释的 console 应该通过",
    shouldPass: true,
  },
  {
    ruleName: "semi",
    code: "const x = 1",
    ruleConfig: ["error", "always"],
    description: "测试缺少分号应该报错",
    shouldPass: false,
  },
  {
    ruleName: "semi",
    code: "const x = 1;",
    ruleConfig: ["error", "always"],
    description: "测试有分号应该通过",
    shouldPass: true,
  },
];

/**
 * 运行示例测试
 */
async function runExampleTests() {
  console.log("🚀 开始 ESLint Rule 测试...\n");

  const tester = new ESLintRuleTester();
  const results = await tester.testRules(exampleTestCases);
  const summary = tester.generateReport(results);

  return summary;
}

/**
 * 命令行接口
 */
async function main() {
  const args = process.argv.slice(2);

  if (args.includes("--help") || args.includes("-h")) {
    console.log(`
ESLint Rule 测试脚本

用法:
  node runner.js [选项]

选项:
  --help, -h     显示帮助信息
  --example      运行示例测试
  --rule <name>  测试特定规则
  --code <code>  测试特定代码
  --config <cfg> 规则配置 (默认: "error")

示例:
  node runner.js --example
  node runner.js --rule no-console --code "console.log('test')"
  node runner.js --rule semi --code "const x = 1" --config "error"
    `);
    return;
  }

  if (args.includes("--example")) {
    await runExampleTests();
    return;
  }

  const ruleIndex = args.indexOf("--rule");
  const codeIndex = args.indexOf("--code");
  const configIndex = args.indexOf("--config");

  if (ruleIndex !== -1 && codeIndex !== -1) {
    const ruleName = args[ruleIndex + 1];
    const code = args[codeIndex + 1];
    const ruleConfig = configIndex !== -1 ? args[configIndex + 1] : "error";

    const tester = new ESLintRuleTester();
    const result = await tester.testRule(ruleName, code, ruleConfig);

    console.log("\n🔍 单个规则测试结果:\n");
    console.log(`规则: ${result.ruleName}`);
    console.log(`代码: ${code}`);
    console.log(`配置: ${JSON.stringify(ruleConfig)}`);

    if (result.messages.length === 0) {
      console.log("✅ 通过: 无错误或警告");
    } else {
      console.log(`❌ 失败: ${result.messages.length} 个问题`);
      for (const msg of result.messages) {
        const severity = msg.severity === 2 ? "错误" : "警告";
        console.log(
          `   ${severity}: ${msg.message} (行 ${msg.line}, 列 ${msg.column})`,
        );
      }
    }
    return;
  }

  // 默认运行示例测试
  console.log("未指定参数，运行示例测试...\n");
  await runExampleTests();
}

// 如果是直接运行此文件
if (import.meta.url === `file://${process.argv[1]}`) {
  main().catch(console.error);
}

export { ESLintRuleTester, runExampleTests };
